Goals

Notes

rm(list=ls())
library("readxl")
library(quantmod)
library(dplyr)
library(ggplot2)

I. Loading and Preprocessing of Excel file

The file below was downloaded 26/10/2020 from the TSX website above. File contains first some rows with non-relevant information to skip

issuers <- read_excel(paste("../../../data_tmp/tsx-andamp-tsxv-listed", 
                            "-companies-2020-10-16-en-1.xlsx", sep=""), 
                      sheet=2, skip=6)

-
/
                                                                                                                                          
head(issuers, 2)
colnames(issuers) <- lapply(str_replace_all(colnames(issuers), "[\r\n -$\\(\\)\\-]", "_"), FUN=tolower)

Discard companies from the sector Real Estate Operating Companies as not relevant based on Elton’s comments.

issuers <- issuers %>% filter(real_estate_sub_sector != 
                      "Real Estate Operating Companies")
real_estate <- filter(issuers, !is.na(issuers[, 'real_estate_sub_sector']))[,  c("real_estate_sub_sector", "name", "root__ticker", "market_cap__c____30_september_2020")]
head(real_estate)

Download of Stocks based on Tickers

Root ticker are not representative of the TSX

head(real_estate)  

Use ticker column to download data. Try statement to catch errors.

#stock_name <- "BPY-UN.TO"
get_stockdata <- function(stock_name_root) {
  out <- try ({
    stock_name <- paste(stock_name_root, "-UN.TO", sep="")
    stock <- getSymbols(stock_name, src = "yahoo", auto.assign = FALSE) 
    # calculate monthly returns instead of using all stock data
    stock = monthlyReturn(stock)
    colnames(stock) <- sapply(colnames(stock), function (colstock) str_split(colstock, "\\.")[[1]][length(str_split(colstock, "\\.")[[1]])])
    stock <- data.frame(date=index(stock), coredata(stock))
    stock$stock_name <- rep(stock_name, nrow(stock))
    stock$stock_name_root <- rep(stock_name_root, nrow(stock))
    stock
  })
  
  # if stock is not available as "[stockname]-UN.TO", try "[stockname"].TO"
  if (class(out) == "try-error") {
  
    out <- try ({
      stock_name <- paste(stock_name_root, ".TO", sep="")
      stock <- getSymbols(stock_name, src = "yahoo", auto.assign = FALSE) 
    # calculate monthly returns instead of using all stock data
      stock = monthlyReturn(stock)
      colnames(stock) <- sapply(colnames(stock), function (colstock) str_split(colstock, "\\.")[[1]][length(str_split(colstock, "\\.")[[1]])])
      stock <- data.frame(date=index(stock), coredata(stock))
      stock$stock_name <- rep(stock_name, nrow(stock))
      stock$stock_name_root <- rep(stock_name_root, nrow(stock))
      stock
    })
  }
  
  out
  
  }
start.time <- Sys.time()
get_stock_series <- lapply(real_estate$root__ticker, get_stockdata)
AP-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataHOT-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataAX-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataAPR-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataBEI-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataBRE-UN.TO download failed; trying again.Error in getSymbols.yahoo(Symbols = "BRE-UN.TO", env = <environment>,  : 
  Unable to import “BRE-UN.TO”.
BRE-UN.TO download failed after two attempts. Error message:
HTTP error 404.
BRE.TO download failed; trying again.Warning in for (i in seq_len(n)) { :
  closing unused connection 5 (https://query1.finance.yahoo.com/v7/finance/download/BRE.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=nl4VMJD9Hc5)
Warning in for (i in seq_len(n)) { :
  closing unused connection 4 (https://query1.finance.yahoo.com/v7/finance/download/BRE-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=nl4VMJD9Hc5)
Warning in for (i in seq_len(n)) { :
  closing unused connection 3 (https://query1.finance.yahoo.com/v7/finance/download/BRE-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=NcIouEhK9yv)
BPO-UN.TO download failed; trying again.Error in getSymbols.yahoo(Symbols = "BPO-UN.TO", env = <environment>,  : 
  Unable to import “BPO-UN.TO”.
BPO-UN.TO download failed after two attempts. Error message:
HTTP error 404.
BPO.TO download failed; trying again.Error in getSymbols.yahoo(Symbols = "BPO.TO", env = <environment>, verbose = FALSE,  : 
  Unable to import “BPO.TO”.
BPO.TO download failed after two attempts. Error message:
HTTP error 404.
BPY-UN.TO download failed; trying again.BPY-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataHOM-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataBTB-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataCAR-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataCSH-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataCHP-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataCUF-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataCRR-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataCRT-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataDRA-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataDIR-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataD-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataDRM-UN.TO download failed; trying again.Error in getSymbols.yahoo(Symbols = "DRM-UN.TO", env = <environment>,  : 
  Unable to import “DRM-UN.TO”.
DRM-UN.TO download failed after two attempts. Error message:
HTTP error 404.
DRM.TO download failed; trying again.ERE-UN.TO download failed; trying again.Error in getSymbols.yahoo(Symbols = "ERE-UN.TO", env = <environment>,  : 
  Unable to import “ERE-UN.TO”.
ERE-UN.TO download failed after two attempts. Error message:
HTTP error 404.
ERE.TO download failed; trying again.Error in getSymbols.yahoo(Symbols = "ERE.TO", env = <environment>, verbose = FALSE,  : 
  Unable to import “ERE.TO”.
ERE.TO download failed after two attempts. Error message:
HTTP error 404.
EXE-UN.TO download failed; trying again.Error in getSymbols.yahoo(Symbols = "EXE-UN.TO", env = <environment>,  : 
  Unable to import “EXE-UN.TO”.
EXE-UN.TO download failed after two attempts. Error message:
HTTP error 404.
EXE.TO download failed; trying again.FCR-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataFSV-UN.TO download failed; trying again.Error in getSymbols.yahoo(Symbols = "FSV-UN.TO", env = <environment>,  : 
  Unable to import “FSV-UN.TO”.
FSV-UN.TO download failed after two attempts. Error message:
HTTP error 404.
FSV.TO download failed; trying again.GDC-UN.TO download failed; trying again.Error in getSymbols.yahoo(Symbols = "GDC-UN.TO", env = <environment>,  : 
  Unable to import “GDC-UN.TO”.
GDC-UN.TO download failed after two attempts. Error message:
HTTP error 404.
GDC.TO download failed; trying again.HR-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataINO-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataIIP-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataIVQ-UN.TO download failed; trying again.Error in getSymbols.yahoo(Symbols = "IVQ-UN.TO", env = <environment>,  : 
  Unable to import “IVQ-UN.TO”.
IVQ-UN.TO download failed after two attempts. Error message:
HTTP error 404.
IVQ.TO download failed; trying again.DR-UN.TO download failed; trying again.Error in getSymbols.yahoo(Symbols = "DR-UN.TO", env = <environment>, verbose = FALSE,  : 
  Unable to import “DR-UN.TO”.
DR-UN.TO download failed after two attempts. Error message:
HTTP error 404.
DR.TO download failed; trying again.MRD-UN.TO download failed; trying again.Error in getSymbols.yahoo(Symbols = "MRD-UN.TO", env = <environment>,  : 
  Unable to import “MRD-UN.TO”.
MRD-UN.TO download failed after two attempts. Error message:
HTTP error 404.
MRD.TO download failed; trying again.MR-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataMI-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataMRC-UN.TO download failed; trying again.Error in getSymbols.yahoo(Symbols = "MRC-UN.TO", env = <environment>,  : 
  Unable to import “MRC-UN.TO”.
MRC-UN.TO download failed after two attempts. Error message:
HTTP error 404.
MRC.TO download failed; trying again.MRG-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataMRT-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataNVU-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataNWH-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataPLZ-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataPRV-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataREI-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataSIA-UN.TO download failed; trying again.Error in getSymbols.yahoo(Symbols = "SIA-UN.TO", env = <environment>,  : 
  Unable to import “SIA-UN.TO”.
SIA-UN.TO download failed after two attempts. Error message:
HTTP error 404.
SIA.TO download failed; trying again.SIA.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataSGR-UN.TO download failed; trying again.Error in getSymbols.yahoo(Symbols = "SGR-UN.TO", env = <environment>,  : 
  Unable to import “SGR-UN.TO”.
SGR-UN.TO download failed after two attempts. Error message:
HTTP error 404.
SGR.TO download failed; trying again.Error in getSymbols.yahoo(Symbols = "SGR.TO", env = <environment>, verbose = FALSE,  : 
  Unable to import “SGR.TO”.
SGR.TO download failed after two attempts. Error message:
HTTP error 404.
SOT-UN.TO download failed; trying again.SOT-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataSRU-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataSMU-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataTNT-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataWFC-UN.TO download failed; trying again.Error in getSymbols.yahoo(Symbols = "WFC-UN.TO", env = <environment>,  : 
  Unable to import “WFC-UN.TO”.
WFC-UN.TO download failed after two attempts. Error message:
HTTP error 404.
WFC.TO download failed; trying again.WIR-UN.TO contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.missing values removed from dataWarning in give.length :
  closing unused connection 46 (https://query2.finance.yahoo.com/v7/finance/download/WFC.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=M5w7sOsNvPB)
Warning in give.length :
  closing unused connection 45 (https://query2.finance.yahoo.com/v7/finance/download/WFC-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=M5w7sOsNvPB)
Warning in give.length :
  closing unused connection 44 (https://query2.finance.yahoo.com/v7/finance/download/WFC-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=6KRUV9eJGJG)
Warning in give.length :
  closing unused connection 43 (https://query1.finance.yahoo.com/v7/finance/download/SOT-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=pmLIa4.gDQY)
Warning in give.length :
  closing unused connection 42 (https://query1.finance.yahoo.com/v7/finance/download/SGR.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=pmLIa4.gDQY)
Warning in give.length :
  closing unused connection 41 (https://query2.finance.yahoo.com/v7/finance/download/SGR.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=Uk9oVSWRrOk)
Warning in give.length :
  closing unused connection 40 (https://query2.finance.yahoo.com/v7/finance/download/SGR-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=Uk9oVSWRrOk)
Warning in give.length :
  closing unused connection 39 (https://query2.finance.yahoo.com/v7/finance/download/SGR-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=C.7/ROl4aHg)
Warning in give.length :
  closing unused connection 38 (https://query1.finance.yahoo.com/v7/finance/download/SIA.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=y0UdPNvuvZK)
Warning in give.length :
  closing unused connection 37 (https://query2.finance.yahoo.com/v7/finance/download/SIA-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=y0UdPNvuvZK)
Warning in give.length :
  closing unused connection 36 (https://query1.finance.yahoo.com/v7/finance/download/SIA-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=BHla2xJaBvD)
Warning in give.length :
  closing unused connection 35 (https://query2.finance.yahoo.com/v7/finance/download/MRC.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=87Fsk8iwI2Q)
Warning in give.length :
  closing unused connection 34 (https://query2.finance.yahoo.com/v7/finance/download/MRC-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=87Fsk8iwI2Q)
Warning in give.length :
  closing unused connection 33 (https://query2.finance.yahoo.com/v7/finance/download/MRC-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=V2vxkijwfAk)
Warning in give.length :
  closing unused connection 32 (https://query2.finance.yahoo.com/v7/finance/download/MRD.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=W1etzULAOmn)
Warning in give.length :
  closing unused connection 31 (https://query2.finance.yahoo.com/v7/finance/download/MRD-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=W1etzULAOmn)
Warning in give.length :
  closing unused connection 30 (https://query2.finance.yahoo.com/v7/finance/download/MRD-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=Ht/F4yKThEH)
Warning in give.length :
  closing unused connection 29 (https://query2.finance.yahoo.com/v7/finance/download/DR.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=SVaFsxbcFjd)
Warning in give.length :
  closing unused connection 28 (https://query2.finance.yahoo.com/v7/finance/download/DR-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=SVaFsxbcFjd)
Warning in give.length :
  closing unused connection 27 (https://query1.finance.yahoo.com/v7/finance/download/DR-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=ysu8EfYbbSB)
Warning in give.length :
  closing unused connection 26 (https://query1.finance.yahoo.com/v7/finance/download/IVQ.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=sBek06jn/nm)
Warning in give.length :
  closing unused connection 25 (https://query1.finance.yahoo.com/v7/finance/download/IVQ-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=sBek06jn/nm)
Warning in give.length :
  closing unused connection 24 (https://query2.finance.yahoo.com/v7/finance/download/IVQ-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=czs7jtF1.Hh)
Warning in give.length :
  closing unused connection 23 (https://query1.finance.yahoo.com/v7/finance/download/GDC.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=F.PmmZDRfhG)
Warning in give.length :
  closing unused connection 22 (https://query1.finance.yahoo.com/v7/finance/download/GDC-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=F.PmmZDRfhG)
Warning in give.length :
  closing unused connection 21 (https://query1.finance.yahoo.com/v7/finance/download/GDC-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=H7tQebwunW4)
Warning in give.length :
  closing unused connection 20 (https://query1.finance.yahoo.com/v7/finance/download/FSV.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=ptaiPK9aWR1)
Warning in give.length :
  closing unused connection 19 (https://query2.finance.yahoo.com/v7/finance/download/FSV-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=ptaiPK9aWR1)
Warning in give.length :
  closing unused connection 18 (https://query1.finance.yahoo.com/v7/finance/download/FSV-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=1/fy1zhye1Q)
Warning in give.length :
  closing unused connection 17 (https://query1.finance.yahoo.com/v7/finance/download/EXE.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=I/2tiCmgP7.)
Warning in give.length :
  closing unused connection 16 (https://query1.finance.yahoo.com/v7/finance/download/EXE-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=I/2tiCmgP7.)
Warning in give.length :
  closing unused connection 15 (https://query1.finance.yahoo.com/v7/finance/download/EXE-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=xIbHqGagIDx)
Warning in give.length :
  closing unused connection 14 (https://query1.finance.yahoo.com/v7/finance/download/ERE.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=xIbHqGagIDx)
Warning in give.length :
  closing unused connection 13 (https://query1.finance.yahoo.com/v7/finance/download/ERE.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=3z7V5.M3EfI)
Warning in give.length :
  closing unused connection 12 (https://query1.finance.yahoo.com/v7/finance/download/ERE-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=3z7V5.M3EfI)
Warning in give.length :
  closing unused connection 11 (https://query1.finance.yahoo.com/v7/finance/download/ERE-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=0fce15F478c)
Warning in give.length :
  closing unused connection 10 (https://query2.finance.yahoo.com/v7/finance/download/DRM.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=bYrZEcpla0V)
Warning in give.length :
  closing unused connection 9 (https://query2.finance.yahoo.com/v7/finance/download/DRM-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=bYrZEcpla0V)
Warning in give.length :
  closing unused connection 8 (https://query2.finance.yahoo.com/v7/finance/download/DRM-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=K3KhgFHo9vF)
Warning in give.length :
  closing unused connection 7 (https://query2.finance.yahoo.com/v7/finance/download/BPY-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=/y2DZjZodnj)
Warning in give.length :
  closing unused connection 6 (https://query2.finance.yahoo.com/v7/finance/download/BPO.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=/y2DZjZodnj)
Warning in give.length :
  closing unused connection 5 (https://query1.finance.yahoo.com/v7/finance/download/BPO.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=o1KlxQmzm0l)
Warning in give.length :
  closing unused connection 4 (https://query2.finance.yahoo.com/v7/finance/download/BPO-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=o1KlxQmzm0l)
Warning in give.length :
  closing unused connection 3 (https://query1.finance.yahoo.com/v7/finance/download/BPO-UN.TO?period1=1167609600&period2=1604016000&interval=1d&events=history&crumb=y3ze1kyJkU9)
print(paste("total download time :", Sys.time() - start.time, "s"))
[1] "total download time : 1.38832774957021 s"

Identify which time series was not downloaded successfully and print their error messages. Successfull stocks are saved in stock_series.

downloaded <- list()
stock_series <- list()
j = 1
k = 1
for (i in 1:length(get_stock_series)) {
  if (class(get_stock_series[[i]]) == "try-error") {
    #missing_data_log[[k]] <- get_stock_series[[i]]
    print(get_stock_series[[i]])
    downloaded[[i]] <- FALSE
  } else {
    downloaded[[i]] <- TRUE
    stock_series[[j]] <- get_stock_series[[i]]
    j <- j + 1
  }
}
[1] "Error in getSymbols.yahoo(Symbols = \"BPO.TO\", env = <environment>, verbose = FALSE,  : \n  Unable to import “BPO.TO”.\nBPO.TO download failed after two attempts. Error message:\nHTTP error 404.\n"
attr(,"class")
[1] "try-error"
attr(,"condition")
<simpleError in getSymbols.yahoo(Symbols = "BPO.TO", env = <environment>, verbose = FALSE,     warnings = TRUE, auto.assign = FALSE, .has1sym. = TRUE): Unable to import “BPO.TO”.
BPO.TO download failed after two attempts. Error message:
HTTP error 404.>
[1] "Error in getSymbols.yahoo(Symbols = \"ERE.TO\", env = <environment>, verbose = FALSE,  : \n  Unable to import “ERE.TO”.\nERE.TO download failed after two attempts. Error message:\nHTTP error 404.\n"
attr(,"class")
[1] "try-error"
attr(,"condition")
<simpleError in getSymbols.yahoo(Symbols = "ERE.TO", env = <environment>, verbose = FALSE,     warnings = TRUE, auto.assign = FALSE, .has1sym. = TRUE): Unable to import “ERE.TO”.
ERE.TO download failed after two attempts. Error message:
HTTP error 404.>
[1] "Error in getSymbols.yahoo(Symbols = \"SGR.TO\", env = <environment>, verbose = FALSE,  : \n  Unable to import “SGR.TO”.\nSGR.TO download failed after two attempts. Error message:\nHTTP error 404.\n"
attr(,"class")
[1] "try-error"
attr(,"condition")
<simpleError in getSymbols.yahoo(Symbols = "SGR.TO", env = <environment>, verbose = FALSE,     warnings = TRUE, auto.assign = FALSE, .has1sym. = TRUE): Unable to import “SGR.TO”.
SGR.TO download failed after two attempts. Error message:
HTTP error 404.>
real_estate['downloaded'] <- unlist(list(downloaded))

Analysis of missing data

A small amount of stocks were not downloaded/are not available

table(real_estate$downloaded)

FALSE  TRUE 
    3    46 

The following 3 stocks could not be downloaded. In fact * BPO.TO: shows NA values in Yahoo: https://ca.finance.yahoo.com/quote/bpo.to/ * ERE: not available on Yahoo, should be available on TSX, according to https://www.eresreit.com. As its European I discard the ticker for now. * SGR: should be availalbe at https://ca.finance.yahoo.com/quote/SGR-UN.TO/ Note that all 3 missing stocks are part of the Industrial/Office/Retail/Residential subsector for which plenty of companies are available already. Discard the companies below in further work.

real_estate[ !real_estate$downloaded, ]

II. Analysis of stocks Properties

stock_series <- bind_rows(stock_series)
head(stock_series)

add sub-sector information to stocks

stock_series <- merge(stock_series, real_estate, by.x="stock_name_root", by.y="root__ticker", all=FALSE)
head(stock_series, 2)
table(real_estate[real_estate$downloaded, ]$real_estate_sub_sector)

                         Diversified Industrial/Office/Retail/Residential Real Estate Development and Services                          Specialized 
                                   7                                   30                                    3                                    6 

1. Category: Diversified

Most companies go back to 2007 but those with the largest market cap go back only to 2012. Fair amount of distribution.

stock_series_stats_div <- stock_series %>% 
  filter(real_estate_sub_sector=="Diversified") %>%
  group_by(stock_name_root) %>%
      summarize(
        min = min(date, na.rm=TRUE),
        max = max(date, na.rm=TRUE),
        real_estate_sub_sector = unique(real_estate_sub_sector),
        market_cap__c____30_september_2020 = 
          max(market_cap__c____30_september_2020),
        name = unique(name),
        .groups = "keep"
      )
stock_series_stats_div$market_cap_fraction <- 
  stock_series_stats_div$market_cap__c____30_september_2020/sum(stock_series_stats_div$market_cap__c____30_september_2020)
stock_series_stats_div$real_estate_sub_sector <- NULL
stock_series_stats_div
p <- ggplot(data = filter(stock_series, real_estate_sub_sector == "Diversified")) + 
              geom_line(aes(x = as.Date(date), y = returns, group=stock_name_root, color=name, linetype=name)) +
                labs(title = "Category - Diversified",
                   x = "reference month", y = "monthly stock returns", 
                            group= "Ticker", color= "Ticker")
ggplotly(p, width=880, height=450)

2. Category: Specialized

The companies with a largest market capitalization exist also the longest. If we would weight according to capitalization, then only two companies would dominate an categorical indicator.

stock_series_stats_spec <- stock_series %>% 
  filter(real_estate_sub_sector=="Specialized") %>%
  group_by(stock_name_root) %>%
      summarize(
        min = min(date, na.rm=TRUE),
        max = max(date, na.rm=TRUE),
        real_estate_sub_sector = unique(real_estate_sub_sector),
        market_cap__c____30_september_2020 = 
          max(market_cap__c____30_september_2020),
        name = unique(name),
        .groups = "keep"
      )
stock_series_stats_spec$market_cap_fraction <- 
  stock_series_stats_spec$market_cap__c____30_september_2020/sum(stock_series_stats_spec$market_cap__c____30_september_2020)
stock_series_stats_spec$real_estate_sub_sector <- NULL
stock_series_stats_spec
p <- ggplot(data = filter(stock_series, real_estate_sub_sector == "Specialized")) + 
              geom_line(aes(x = as.Date(date), y = returns, group=stock_name_root, color=name, linetype=name)) +
                labs(title = "Category - Specialized",
                   x = "reference month", y = "close stock value", 
                            group= "Ticker", color= "Ticker")
ggplotly(p, width=880, height=450)

3. Category: Real Estate Development and Services

All 3 companies exist for a longer time at the stock market and have a similar market cap. One company would dominate a categorical indicator with 50%.

stock_series_stats_real <- stock_series %>% 
  filter(real_estate_sub_sector=="Real Estate Development and Services") %>%
  group_by(stock_name_root) %>%
      summarize(
        min = min(date, na.rm=TRUE),
        max = max(date, na.rm=TRUE),
        real_estate_sub_sector = unique(real_estate_sub_sector),
        market_cap__c____30_september_2020 = 
          max(market_cap__c____30_september_2020),
        name = unique(name),
        .groups = "keep"
      )
stock_series_stats_real$market_cap_fraction <- 
  stock_series_stats_real$market_cap__c____30_september_2020/sum(stock_series_stats_real$market_cap__c____30_september_2020)
stock_series_stats_real$real_estate_sub_sector <- NULL
stock_series_stats_real
p <- ggplot(data = filter(stock_series, real_estate_sub_sector == "Real Estate Development and Services")) + 
              geom_line(aes(x = as.Date(date), y = returns, group=stock_name_root, color=name, linetype=name)) +
                labs(title = "Category - Real Estate Development and Services",
                   x = "reference month", y = "close stock value", 
                            group= "Ticker", color= "Ticker")
ggplotly(p, width=780, height=450)

4. Category: Industrial/Office/Retail/Residential

stock_series_stats_ind <- stock_series %>% 
  filter(real_estate_sub_sector=="Industrial/Office/Retail/Residential") %>%
  group_by(stock_name_root) %>%
      summarize(
        min = min(date, na.rm=TRUE),
        max = max(date, na.rm=TRUE),
        real_estate_sub_sector = unique(real_estate_sub_sector),
        market_cap__c____30_september_2020 = 
          max(market_cap__c____30_september_2020),
        .groups = "keep"
      )
stock_series_stats_ind$market_cap_fraction <- 
  stock_series_stats_ind$market_cap__c____30_september_2020/sum(stock_series_stats_ind$market_cap__c____30_september_2020)
stock_series_stats_ind$real_estate_sub_sector <- NULL
stock_series_stats_ind

Top companies in company for market cap indicates that the market cap is fairly distributed and there may be a less dependency of a categorical indicator on individual companies.

head(stock_series_stats_ind %>% arrange(across(market_cap_fraction, desc)), 10)
p <- ggplot(data = filter(stock_series, real_estate_sub_sector == "Industrial/Office/Retail/Residential")) + 
              geom_line(aes(x = as.Date(date), y = returns, group=stock_name_root, color=name, linetype=name)) +
                labs(title = "Category - Industrial/Office/Retail/Residential",
                   x = "reference month", y = "close stock value", 
                            group= "Ticker", color= "Ticker")
ggplotly(p, width=880, height=450)

5. All Categories

stock_series_stats_all <- stock_series %>% 
  group_by(stock_name_root) %>%
      summarize(
        min = min(date, na.rm=TRUE),
        max = max(date, na.rm=TRUE),
        real_estate_sub_sector = unique(real_estate_sub_sector),
        market_cap__c____30_september_2020 = 
          max(market_cap__c____30_september_2020),
        .groups = "keep"
      )
stock_series_stats_all$market_cap_fraction <- 
  stock_series_stats_all$market_cap__c____30_september_2020/sum(stock_series_stats_all$market_cap__c____30_september_2020)
stock_series_stats_all$real_estate_sub_sector <- NULL
stock_series_stats_all

Fairly well distributed.

head(stock_series_stats_all %>% arrange(across(market_cap_fraction, desc)), 10)
p <- ggplot(data = stock_series) + 
              geom_line(aes(x = as.Date(date), y = returns, group=stock_name_root, alpha=0.2)) +
                labs(title = "All tickers",
                   x = "reference month", y = "close stock value", 
                            group= "Ticker", color= "Ticker")
ggplotly(p, width=880, height=450)
LS0tCnRpdGxlOiAiRURBIG9uIE5ldyBUU1ggTGlzdCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwotLS0KCgojIyMgR29hbHMKCiogQW5hbHlzZSBjb21wb3NpdGlvbiBvZiBzdG9ja3MgZnJvbSBUU1ggSXNzdWVycyByZWxhdGVkIHRvIENvbnN0cnVjdGlvbiBhbmQgUmVhbCBFc3RhdGUKCiMjIyBOb3RlcwoKKiBEYXRhIGRpcmVjdGx5IGZyb20gVFNYIGF0IGh0dHBzOi8vd3d3LnRzeC5jb20vbGlzdGluZ3MvY3VycmVudC1tYXJrZXQtc3RhdGlzdGljcwphbmQgc3BlY2lmaWNhbGx5LiBUaGlzIGRhdGEgd2Ugd291bGQgd2FudCB0byBpbmdlc3QgYXQgc29tZSBwb2ludC4KCmBgYHtyfQpybShsaXN0PWxzKCkpCmBgYAoKCmBgYHtyfQpsaWJyYXJ5KCJyZWFkeGwiKQpsaWJyYXJ5KHF1YW50bW9kKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncGxvdDIpCmBgYAoKIyMgSS4gTG9hZGluZyBhbmQgUHJlcHJvY2Vzc2luZyBvZiBFeGNlbCBmaWxlCgoKVGhlIGZpbGUgYmVsb3cgd2FzIGRvd25sb2FkZWQgMjYvMTAvMjAyMCBmcm9tIHRoZSBUU1ggd2Vic2l0ZSBhYm92ZS4KRmlsZSBjb250YWlucyBmaXJzdCBzb21lIHJvd3Mgd2l0aCBub24tcmVsZXZhbnQgaW5mb3JtYXRpb24gdG8gc2tpcApgYGB7cn0KaXNzdWVycyA8LSByZWFkX2V4Y2VsKHBhc3RlKCIuLi8uLi8uLi9kYXRhX3RtcC90c3gtYW5kYW1wLXRzeHYtbGlzdGVkIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiLWNvbXBhbmllcy0yMDIwLTEwLTE2LWVuLTEueGxzeCIsIHNlcD0iIiksIAogICAgICAgICAgICAgICAgICAgICAgc2hlZXQ9Miwgc2tpcD02KQpgYGAKCmBgYHtyfQpoZWFkKGlzc3VlcnMsIDIpCmBgYAoKYGBge3J9CmNvbG5hbWVzKGlzc3VlcnMpIDwtIGxhcHBseShzdHJfcmVwbGFjZV9hbGwoY29sbmFtZXMoaXNzdWVycyksICJbXHJcbiAtJFxcKFxcKVxcLV0iLCAiXyIpLCBGVU49dG9sb3dlcikKYGBgCgoKRGlzY2FyZCBjb21wYW5pZXMgZnJvbSB0aGUgc2VjdG9yIGBSZWFsIEVzdGF0ZSBPcGVyYXRpbmcgQ29tcGFuaWVzYCBhcyBub3QKcmVsZXZhbnQgYmFzZWQgb24gRWx0b24ncyBjb21tZW50cy4KYGBge3J9Cmlzc3VlcnMgPC0gaXNzdWVycyAlPiUgZmlsdGVyKHJlYWxfZXN0YXRlX3N1Yl9zZWN0b3IgIT0gCiAgICAgICAgICAgICAgICAgICAgICAiUmVhbCBFc3RhdGUgT3BlcmF0aW5nIENvbXBhbmllcyIpCmBgYAoKYGBge3J9CnJlYWxfZXN0YXRlIDwtIGZpbHRlcihpc3N1ZXJzLCAhaXMubmEoaXNzdWVyc1ssICdyZWFsX2VzdGF0ZV9zdWJfc2VjdG9yJ10pKVssICBjKCJyZWFsX2VzdGF0ZV9zdWJfc2VjdG9yIiwgIm5hbWUiLCAicm9vdF9fdGlja2VyIiwgIm1hcmtldF9jYXBfX2NfX19fMzBfc2VwdGVtYmVyXzIwMjAiKV0KaGVhZChyZWFsX2VzdGF0ZSkKYGBgCgoKIyMjIERvd25sb2FkIG9mIFN0b2NrcyBiYXNlZCBvbiBUaWNrZXJzCgpSb290IHRpY2tlciBhcmUgbm90IHJlcHJlc2VudGF0aXZlIG9mIHRoZSBUU1gKCmBgYHtyfQpoZWFkKHJlYWxfZXN0YXRlKSAgCmBgYAoKClVzZSBgdGlja2VyYCBjb2x1bW4gdG8gZG93bmxvYWQgZGF0YS4gVHJ5IHN0YXRlbWVudCB0byBjYXRjaCBlcnJvcnMuCgpgYGB7cn0KI3N0b2NrX25hbWUgPC0gIkJQWS1VTi5UTyIKCmdldF9zdG9ja2RhdGEgPC0gZnVuY3Rpb24oc3RvY2tfbmFtZV9yb290KSB7CgogIG91dCA8LSB0cnkgKHsKICAgIHN0b2NrX25hbWUgPC0gcGFzdGUoc3RvY2tfbmFtZV9yb290LCAiLVVOLlRPIiwgc2VwPSIiKQogICAgc3RvY2sgPC0gZ2V0U3ltYm9scyhzdG9ja19uYW1lLCBzcmMgPSAieWFob28iLCBhdXRvLmFzc2lnbiA9IEZBTFNFKSAKCiAgICAjIGNhbGN1bGF0ZSBtb250aGx5IHJldHVybnMgaW5zdGVhZCBvZiB1c2luZyBhbGwgc3RvY2sgZGF0YQogICAgc3RvY2sgPSBtb250aGx5UmV0dXJuKHN0b2NrKQogICAgY29sbmFtZXMoc3RvY2spIDwtIHNhcHBseShjb2xuYW1lcyhzdG9jayksIGZ1bmN0aW9uIChjb2xzdG9jaykgc3RyX3NwbGl0KGNvbHN0b2NrLCAiXFwuIilbWzFdXVtsZW5ndGgoc3RyX3NwbGl0KGNvbHN0b2NrLCAiXFwuIilbWzFdXSldKQogICAgc3RvY2sgPC0gZGF0YS5mcmFtZShkYXRlPWluZGV4KHN0b2NrKSwgY29yZWRhdGEoc3RvY2spKQogICAgc3RvY2skc3RvY2tfbmFtZSA8LSByZXAoc3RvY2tfbmFtZSwgbnJvdyhzdG9jaykpCiAgICBzdG9jayRzdG9ja19uYW1lX3Jvb3QgPC0gcmVwKHN0b2NrX25hbWVfcm9vdCwgbnJvdyhzdG9jaykpCiAgICBzdG9jawogIH0pCiAgCiAgIyBpZiBzdG9jayBpcyBub3QgYXZhaWxhYmxlIGFzICJbc3RvY2tuYW1lXS1VTi5UTyIsIHRyeSAiW3N0b2NrbmFtZSJdLlRPIgogIGlmIChjbGFzcyhvdXQpID09ICJ0cnktZXJyb3IiKSB7CiAgCiAgICBvdXQgPC0gdHJ5ICh7CiAgICAgIHN0b2NrX25hbWUgPC0gcGFzdGUoc3RvY2tfbmFtZV9yb290LCAiLlRPIiwgc2VwPSIiKQogICAgICBzdG9jayA8LSBnZXRTeW1ib2xzKHN0b2NrX25hbWUsIHNyYyA9ICJ5YWhvbyIsIGF1dG8uYXNzaWduID0gRkFMU0UpIAogICAgIyBjYWxjdWxhdGUgbW9udGhseSByZXR1cm5zIGluc3RlYWQgb2YgdXNpbmcgYWxsIHN0b2NrIGRhdGEKICAgICAgc3RvY2sgPSBtb250aGx5UmV0dXJuKHN0b2NrKQogICAgICBjb2xuYW1lcyhzdG9jaykgPC0gc2FwcGx5KGNvbG5hbWVzKHN0b2NrKSwgZnVuY3Rpb24gKGNvbHN0b2NrKSBzdHJfc3BsaXQoY29sc3RvY2ssICJcXC4iKVtbMV1dW2xlbmd0aChzdHJfc3BsaXQoY29sc3RvY2ssICJcXC4iKVtbMV1dKV0pCiAgICAgIHN0b2NrIDwtIGRhdGEuZnJhbWUoZGF0ZT1pbmRleChzdG9jayksIGNvcmVkYXRhKHN0b2NrKSkKICAgICAgc3RvY2skc3RvY2tfbmFtZSA8LSByZXAoc3RvY2tfbmFtZSwgbnJvdyhzdG9jaykpCiAgICAgIHN0b2NrJHN0b2NrX25hbWVfcm9vdCA8LSByZXAoc3RvY2tfbmFtZV9yb290LCBucm93KHN0b2NrKSkKICAgICAgc3RvY2sKICAgIH0pCiAgfQogIAogIG91dAogIAogIH0KYGBgCgoKYGBge3J9CnN0YXJ0LnRpbWUgPC0gU3lzLnRpbWUoKQpnZXRfc3RvY2tfc2VyaWVzIDwtIGxhcHBseShyZWFsX2VzdGF0ZSRyb290X190aWNrZXIsIGdldF9zdG9ja2RhdGEpCnByaW50KHBhc3RlKCJ0b3RhbCBkb3dubG9hZCB0aW1lIDoiLCBTeXMudGltZSgpIC0gc3RhcnQudGltZSwgInMiKSkKYGBgCgoKSWRlbnRpZnkgd2hpY2ggdGltZSBzZXJpZXMgd2FzIG5vdCBkb3dubG9hZGVkIHN1Y2Nlc3NmdWxseSBhbmQgcHJpbnQgdGhlaXIgCmVycm9yIG1lc3NhZ2VzLiBTdWNjZXNzZnVsbCBzdG9ja3MgYXJlIHNhdmVkIGluIHN0b2NrX3Nlcmllcy4KYGBge3J9CmRvd25sb2FkZWQgPC0gbGlzdCgpCnN0b2NrX3NlcmllcyA8LSBsaXN0KCkKaiA9IDEKayA9IDEKZm9yIChpIGluIDE6bGVuZ3RoKGdldF9zdG9ja19zZXJpZXMpKSB7CiAgaWYgKGNsYXNzKGdldF9zdG9ja19zZXJpZXNbW2ldXSkgPT0gInRyeS1lcnJvciIpIHsKICAgICNtaXNzaW5nX2RhdGFfbG9nW1trXV0gPC0gZ2V0X3N0b2NrX3Nlcmllc1tbaV1dCiAgICBwcmludChnZXRfc3RvY2tfc2VyaWVzW1tpXV0pCiAgICBkb3dubG9hZGVkW1tpXV0gPC0gRkFMU0UKICB9IGVsc2UgewogICAgZG93bmxvYWRlZFtbaV1dIDwtIFRSVUUKICAgIHN0b2NrX3Nlcmllc1tbal1dIDwtIGdldF9zdG9ja19zZXJpZXNbW2ldXQogICAgaiA8LSBqICsgMQogIH0KfQpyZWFsX2VzdGF0ZVsnZG93bmxvYWRlZCddIDwtIHVubGlzdChsaXN0KGRvd25sb2FkZWQpKQpgYGAKCiMjIyBBbmFseXNpcyBvZiBtaXNzaW5nIGRhdGEKCkEgc21hbGwgYW1vdW50IG9mIHN0b2NrcyB3ZXJlIG5vdCBkb3dubG9hZGVkL2FyZSBub3QgYXZhaWxhYmxlCmBgYHtyfQp0YWJsZShyZWFsX2VzdGF0ZSRkb3dubG9hZGVkKQpgYGAKClRoZSBmb2xsb3dpbmcgMyBzdG9ja3MgY291bGQgbm90IGJlIGRvd25sb2FkZWQuIEluIGZhY3QgCiogQlBPLlRPOiBzaG93cyBOQSB2YWx1ZXMgaW4gWWFob286IGh0dHBzOi8vY2EuZmluYW5jZS55YWhvby5jb20vcXVvdGUvYnBvLnRvLwoqIEVSRTogbm90IGF2YWlsYWJsZSBvbiBZYWhvbywgc2hvdWxkIGJlIGF2YWlsYWJsZSBvbiBUU1gsIGFjY29yZGluZyAKdG8gaHR0cHM6Ly93d3cuZXJlc3JlaXQuY29tLiBBcyBpdHMgRXVyb3BlYW4gSSBkaXNjYXJkIHRoZSB0aWNrZXIgZm9yIG5vdy4KKiBTR1I6IHNob3VsZCBiZSBhdmFpbGFsYmUgYXQgaHR0cHM6Ly9jYS5maW5hbmNlLnlhaG9vLmNvbS9xdW90ZS9TR1ItVU4uVE8vCk5vdGUgdGhhdCBhbGwgMyBtaXNzaW5nIHN0b2NrcyBhcmUgcGFydCBvZiB0aGUgCmBJbmR1c3RyaWFsL09mZmljZS9SZXRhaWwvUmVzaWRlbnRpYWxgIHN1YnNlY3RvciBmb3Igd2hpY2ggcGxlbnR5IG9mIGNvbXBhbmllcwphcmUgYXZhaWxhYmxlIGFscmVhZHkuIERpc2NhcmQgdGhlIGNvbXBhbmllcyBiZWxvdyBpbiBmdXJ0aGVyIHdvcmsuCmBgYHtyfQpyZWFsX2VzdGF0ZVsgIXJlYWxfZXN0YXRlJGRvd25sb2FkZWQsIF0KYGBgCgoKCiMjIElJLiBBbmFseXNpcyBvZiBzdG9ja3MgUHJvcGVydGllcwoKYGBge3J9CnN0b2NrX3NlcmllcyA8LSBiaW5kX3Jvd3Moc3RvY2tfc2VyaWVzKQpgYGAKCgoKYGBge3J9CmhlYWQoc3RvY2tfc2VyaWVzKQpgYGAKCmFkZCBzdWItc2VjdG9yIGluZm9ybWF0aW9uIHRvIHN0b2NrcwpgYGB7cn0Kc3RvY2tfc2VyaWVzIDwtIG1lcmdlKHN0b2NrX3NlcmllcywgcmVhbF9lc3RhdGUsIGJ5Lng9InN0b2NrX25hbWVfcm9vdCIsIGJ5Lnk9InJvb3RfX3RpY2tlciIsIGFsbD1GQUxTRSkKaGVhZChzdG9ja19zZXJpZXMsIDIpCmBgYAoKCmBgYHtyfQp0YWJsZShyZWFsX2VzdGF0ZVtyZWFsX2VzdGF0ZSRkb3dubG9hZGVkLCBdJHJlYWxfZXN0YXRlX3N1Yl9zZWN0b3IpCmBgYAoKIyMjIDEuIENhdGVnb3J5OiBEaXZlcnNpZmllZAoKTW9zdCBjb21wYW5pZXMgZ28gYmFjayB0byAyMDA3IGJ1dCB0aG9zZSB3aXRoIHRoZSBsYXJnZXN0IG1hcmtldCBjYXAKZ28gYmFjayBvbmx5IHRvIDIwMTIuIEZhaXIgYW1vdW50IG9mIGRpc3RyaWJ1dGlvbi4KYGBge3J9CnN0b2NrX3Nlcmllc19zdGF0c19kaXYgPC0gc3RvY2tfc2VyaWVzICU+JSAKICBmaWx0ZXIocmVhbF9lc3RhdGVfc3ViX3NlY3Rvcj09IkRpdmVyc2lmaWVkIikgJT4lCiAgZ3JvdXBfYnkoc3RvY2tfbmFtZV9yb290KSAlPiUKICAgICAgc3VtbWFyaXplKAogICAgICAgIG1pbiA9IG1pbihkYXRlLCBuYS5ybT1UUlVFKSwKICAgICAgICBtYXggPSBtYXgoZGF0ZSwgbmEucm09VFJVRSksCiAgICAgICAgcmVhbF9lc3RhdGVfc3ViX3NlY3RvciA9IHVuaXF1ZShyZWFsX2VzdGF0ZV9zdWJfc2VjdG9yKSwKICAgICAgICBtYXJrZXRfY2FwX19jX19fXzMwX3NlcHRlbWJlcl8yMDIwID0gCiAgICAgICAgICBtYXgobWFya2V0X2NhcF9fY19fX18zMF9zZXB0ZW1iZXJfMjAyMCksCiAgICAgICAgbmFtZSA9IHVuaXF1ZShuYW1lKSwKICAgICAgICAuZ3JvdXBzID0gImtlZXAiCiAgICAgICkKc3RvY2tfc2VyaWVzX3N0YXRzX2RpdiRtYXJrZXRfY2FwX2ZyYWN0aW9uIDwtIAogIHN0b2NrX3Nlcmllc19zdGF0c19kaXYkbWFya2V0X2NhcF9fY19fX18zMF9zZXB0ZW1iZXJfMjAyMC9zdW0oc3RvY2tfc2VyaWVzX3N0YXRzX2RpdiRtYXJrZXRfY2FwX19jX19fXzMwX3NlcHRlbWJlcl8yMDIwKQpzdG9ja19zZXJpZXNfc3RhdHNfZGl2JHJlYWxfZXN0YXRlX3N1Yl9zZWN0b3IgPC0gTlVMTApzdG9ja19zZXJpZXNfc3RhdHNfZGl2CmBgYAoKYGBge3IsIGZpZy53aWR0aD0yNCwgZmlnLmhlaWdodD0xMn0KcCA8LSBnZ3Bsb3QoZGF0YSA9IGZpbHRlcihzdG9ja19zZXJpZXMsIHJlYWxfZXN0YXRlX3N1Yl9zZWN0b3IgPT0gIkRpdmVyc2lmaWVkIikpICsgCiAgICAgICAgICAgICAgZ2VvbV9saW5lKGFlcyh4ID0gYXMuRGF0ZShkYXRlKSwgeSA9IHJldHVybnMsIGdyb3VwPXN0b2NrX25hbWVfcm9vdCwgY29sb3I9bmFtZSwgbGluZXR5cGU9bmFtZSkpICsKICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSAiQ2F0ZWdvcnkgLSBEaXZlcnNpZmllZCIsCiAgICAgICAgICAgICAgICAgICB4ID0gInJlZmVyZW5jZSBtb250aCIsIHkgPSAibW9udGhseSBzdG9jayByZXR1cm5zIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cD0gIlRpY2tlciIsIGNvbG9yPSAiVGlja2VyIikKZ2dwbG90bHkocCwgd2lkdGg9ODgwLCBoZWlnaHQ9NDUwKQpgYGAKCgojIyMgMi4gQ2F0ZWdvcnk6IFNwZWNpYWxpemVkCgpUaGUgY29tcGFuaWVzIHdpdGggYSBsYXJnZXN0IG1hcmtldCBjYXBpdGFsaXphdGlvbiBleGlzdCBhbHNvIHRoZSBsb25nZXN0LgpJZiB3ZSB3b3VsZCB3ZWlnaHQgYWNjb3JkaW5nIHRvIGNhcGl0YWxpemF0aW9uLCB0aGVuIG9ubHkgdHdvIGNvbXBhbmllcyB3b3VsZApkb21pbmF0ZSBhbiBjYXRlZ29yaWNhbCBpbmRpY2F0b3IuCmBgYHtyfQpzdG9ja19zZXJpZXNfc3RhdHNfc3BlYyA8LSBzdG9ja19zZXJpZXMgJT4lIAogIGZpbHRlcihyZWFsX2VzdGF0ZV9zdWJfc2VjdG9yPT0iU3BlY2lhbGl6ZWQiKSAlPiUKICBncm91cF9ieShzdG9ja19uYW1lX3Jvb3QpICU+JQogICAgICBzdW1tYXJpemUoCiAgICAgICAgbWluID0gbWluKGRhdGUsIG5hLnJtPVRSVUUpLAogICAgICAgIG1heCA9IG1heChkYXRlLCBuYS5ybT1UUlVFKSwKICAgICAgICByZWFsX2VzdGF0ZV9zdWJfc2VjdG9yID0gdW5pcXVlKHJlYWxfZXN0YXRlX3N1Yl9zZWN0b3IpLAogICAgICAgIG1hcmtldF9jYXBfX2NfX19fMzBfc2VwdGVtYmVyXzIwMjAgPSAKICAgICAgICAgIG1heChtYXJrZXRfY2FwX19jX19fXzMwX3NlcHRlbWJlcl8yMDIwKSwKICAgICAgICBuYW1lID0gdW5pcXVlKG5hbWUpLAogICAgICAgIC5ncm91cHMgPSAia2VlcCIKICAgICAgKQpzdG9ja19zZXJpZXNfc3RhdHNfc3BlYyRtYXJrZXRfY2FwX2ZyYWN0aW9uIDwtIAogIHN0b2NrX3Nlcmllc19zdGF0c19zcGVjJG1hcmtldF9jYXBfX2NfX19fMzBfc2VwdGVtYmVyXzIwMjAvc3VtKHN0b2NrX3Nlcmllc19zdGF0c19zcGVjJG1hcmtldF9jYXBfX2NfX19fMzBfc2VwdGVtYmVyXzIwMjApCnN0b2NrX3Nlcmllc19zdGF0c19zcGVjJHJlYWxfZXN0YXRlX3N1Yl9zZWN0b3IgPC0gTlVMTApzdG9ja19zZXJpZXNfc3RhdHNfc3BlYwpgYGAKCmBgYHtyLCBmaWcud2lkdGg9MjQsIGZpZy5oZWlnaHQ9MTZ9CnAgPC0gZ2dwbG90KGRhdGEgPSBmaWx0ZXIoc3RvY2tfc2VyaWVzLCByZWFsX2VzdGF0ZV9zdWJfc2VjdG9yID09ICJTcGVjaWFsaXplZCIpKSArIAogICAgICAgICAgICAgIGdlb21fbGluZShhZXMoeCA9IGFzLkRhdGUoZGF0ZSksIHkgPSByZXR1cm5zLCBncm91cD1zdG9ja19uYW1lX3Jvb3QsIGNvbG9yPW5hbWUsIGxpbmV0eXBlPW5hbWUpKSArCiAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gIkNhdGVnb3J5IC0gU3BlY2lhbGl6ZWQiLAogICAgICAgICAgICAgICAgICAgeCA9ICJyZWZlcmVuY2UgbW9udGgiLCB5ID0gImNsb3NlIHN0b2NrIHZhbHVlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cD0gIlRpY2tlciIsIGNvbG9yPSAiVGlja2VyIikKZ2dwbG90bHkocCwgd2lkdGg9ODAsIGhlaWdodD00NTApCmBgYAoKCiMjIyAzLiBDYXRlZ29yeTogUmVhbCBFc3RhdGUgRGV2ZWxvcG1lbnQgYW5kIFNlcnZpY2VzCgpBbGwgMyBjb21wYW5pZXMgZXhpc3QgZm9yIGEgbG9uZ2VyIHRpbWUgYXQgdGhlIHN0b2NrIG1hcmtldCBhbmQgaGF2ZSBhIHNpbWlsYXIKbWFya2V0IGNhcC4gT25lIGNvbXBhbnkgd291bGQgZG9taW5hdGUgYSBjYXRlZ29yaWNhbCBpbmRpY2F0b3Igd2l0aCA1MCUuCgpgYGB7cn0Kc3RvY2tfc2VyaWVzX3N0YXRzX3JlYWwgPC0gc3RvY2tfc2VyaWVzICU+JSAKICBmaWx0ZXIocmVhbF9lc3RhdGVfc3ViX3NlY3Rvcj09IlJlYWwgRXN0YXRlIERldmVsb3BtZW50IGFuZCBTZXJ2aWNlcyIpICU+JQogIGdyb3VwX2J5KHN0b2NrX25hbWVfcm9vdCkgJT4lCiAgICAgIHN1bW1hcml6ZSgKICAgICAgICBtaW4gPSBtaW4oZGF0ZSwgbmEucm09VFJVRSksCiAgICAgICAgbWF4ID0gbWF4KGRhdGUsIG5hLnJtPVRSVUUpLAogICAgICAgIHJlYWxfZXN0YXRlX3N1Yl9zZWN0b3IgPSB1bmlxdWUocmVhbF9lc3RhdGVfc3ViX3NlY3RvciksCiAgICAgICAgbWFya2V0X2NhcF9fY19fX18zMF9zZXB0ZW1iZXJfMjAyMCA9IAogICAgICAgICAgbWF4KG1hcmtldF9jYXBfX2NfX19fMzBfc2VwdGVtYmVyXzIwMjApLAogICAgICAgIG5hbWUgPSB1bmlxdWUobmFtZSksCiAgICAgICAgLmdyb3VwcyA9ICJrZWVwIgogICAgICApCnN0b2NrX3Nlcmllc19zdGF0c19yZWFsJG1hcmtldF9jYXBfZnJhY3Rpb24gPC0gCiAgc3RvY2tfc2VyaWVzX3N0YXRzX3JlYWwkbWFya2V0X2NhcF9fY19fX18zMF9zZXB0ZW1iZXJfMjAyMC9zdW0oc3RvY2tfc2VyaWVzX3N0YXRzX3JlYWwkbWFya2V0X2NhcF9fY19fX18zMF9zZXB0ZW1iZXJfMjAyMCkKc3RvY2tfc2VyaWVzX3N0YXRzX3JlYWwkcmVhbF9lc3RhdGVfc3ViX3NlY3RvciA8LSBOVUxMCnN0b2NrX3Nlcmllc19zdGF0c19yZWFsCmBgYAoKYGBge3IsIGZpZy53aWR0aD0yNCwgZmlnLmhlaWdodD0xNH0KcCA8LSBnZ3Bsb3QoZGF0YSA9IGZpbHRlcihzdG9ja19zZXJpZXMsIHJlYWxfZXN0YXRlX3N1Yl9zZWN0b3IgPT0gIlJlYWwgRXN0YXRlIERldmVsb3BtZW50IGFuZCBTZXJ2aWNlcyIpKSArIAogICAgICAgICAgICAgIGdlb21fbGluZShhZXMoeCA9IGFzLkRhdGUoZGF0ZSksIHkgPSByZXR1cm5zLCBncm91cD1zdG9ja19uYW1lX3Jvb3QsIGNvbG9yPW5hbWUsIGxpbmV0eXBlPW5hbWUpKSArCiAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gIkNhdGVnb3J5IC0gUmVhbCBFc3RhdGUgRGV2ZWxvcG1lbnQgYW5kIFNlcnZpY2VzIiwKICAgICAgICAgICAgICAgICAgIHggPSAicmVmZXJlbmNlIG1vbnRoIiwgeSA9ICJjbG9zZSBzdG9jayB2YWx1ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXA9ICJUaWNrZXIiLCBjb2xvcj0gIlRpY2tlciIpCmdncGxvdGx5KHAsIHdpZHRoPTc4MCwgaGVpZ2h0PTQ1MCkKYGBgCgoKIyMjIDQuIENhdGVnb3J5OiBJbmR1c3RyaWFsL09mZmljZS9SZXRhaWwvUmVzaWRlbnRpYWwKCmBgYHtyfQpzdG9ja19zZXJpZXNfc3RhdHNfaW5kIDwtIHN0b2NrX3NlcmllcyAlPiUgCiAgZmlsdGVyKHJlYWxfZXN0YXRlX3N1Yl9zZWN0b3I9PSJJbmR1c3RyaWFsL09mZmljZS9SZXRhaWwvUmVzaWRlbnRpYWwiKSAlPiUKICBncm91cF9ieShzdG9ja19uYW1lX3Jvb3QpICU+JQogICAgICBzdW1tYXJpemUoCiAgICAgICAgbWluID0gbWluKGRhdGUsIG5hLnJtPVRSVUUpLAogICAgICAgIG1heCA9IG1heChkYXRlLCBuYS5ybT1UUlVFKSwKICAgICAgICByZWFsX2VzdGF0ZV9zdWJfc2VjdG9yID0gdW5pcXVlKHJlYWxfZXN0YXRlX3N1Yl9zZWN0b3IpLAogICAgICAgIG1hcmtldF9jYXBfX2NfX19fMzBfc2VwdGVtYmVyXzIwMjAgPSAKICAgICAgICAgIG1heChtYXJrZXRfY2FwX19jX19fXzMwX3NlcHRlbWJlcl8yMDIwKSwKICAgICAgICAuZ3JvdXBzID0gImtlZXAiCiAgICAgICkKc3RvY2tfc2VyaWVzX3N0YXRzX2luZCRtYXJrZXRfY2FwX2ZyYWN0aW9uIDwtIAogIHN0b2NrX3Nlcmllc19zdGF0c19pbmQkbWFya2V0X2NhcF9fY19fX18zMF9zZXB0ZW1iZXJfMjAyMC9zdW0oc3RvY2tfc2VyaWVzX3N0YXRzX2luZCRtYXJrZXRfY2FwX19jX19fXzMwX3NlcHRlbWJlcl8yMDIwKQpzdG9ja19zZXJpZXNfc3RhdHNfaW5kJHJlYWxfZXN0YXRlX3N1Yl9zZWN0b3IgPC0gTlVMTApzdG9ja19zZXJpZXNfc3RhdHNfaW5kCmBgYAoKVG9wIGNvbXBhbmllcyBpbiBjb21wYW55IGZvciBtYXJrZXQgY2FwIGluZGljYXRlcyB0aGF0IHRoZSBtYXJrZXQgY2FwIGlzIGZhaXJseQpkaXN0cmlidXRlZCBhbmQgdGhlcmUgbWF5IGJlIGEgbGVzcyBkZXBlbmRlbmN5IG9mIGEgY2F0ZWdvcmljYWwgaW5kaWNhdG9yIG9uCmluZGl2aWR1YWwgY29tcGFuaWVzLgpgYGB7cn0KCmhlYWQoc3RvY2tfc2VyaWVzX3N0YXRzX2luZCAlPiUgYXJyYW5nZShhY3Jvc3MobWFya2V0X2NhcF9mcmFjdGlvbiwgZGVzYykpLCAxMCkKYGBgCgpgYGB7ciwgZmlnLndpZHRoPTI0LCBmaWcuaGVpZ2h0PTEyfQpwIDwtIGdncGxvdChkYXRhID0gZmlsdGVyKHN0b2NrX3NlcmllcywgcmVhbF9lc3RhdGVfc3ViX3NlY3RvciA9PSAiSW5kdXN0cmlhbC9PZmZpY2UvUmV0YWlsL1Jlc2lkZW50aWFsIikpICsgCiAgICAgICAgICAgICAgZ2VvbV9saW5lKGFlcyh4ID0gYXMuRGF0ZShkYXRlKSwgeSA9IHJldHVybnMsIGdyb3VwPXN0b2NrX25hbWVfcm9vdCwgY29sb3I9bmFtZSwgbGluZXR5cGU9bmFtZSkpICsKICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSAiQ2F0ZWdvcnkgLSBJbmR1c3RyaWFsL09mZmljZS9SZXRhaWwvUmVzaWRlbnRpYWwiLAogICAgICAgICAgICAgICAgICAgeCA9ICJyZWZlcmVuY2UgbW9udGgiLCB5ID0gImNsb3NlIHN0b2NrIHZhbHVlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cD0gIlRpY2tlciIsIGNvbG9yPSAiVGlja2VyIikKZ2dwbG90bHkocCwgd2lkdGg9ODgwLCBoZWlnaHQ9NDUwKQpgYGAKCgojIyA1LiBBbGwgQ2F0ZWdvcmllcwoKYGBge3J9CnN0b2NrX3Nlcmllc19zdGF0c19hbGwgPC0gc3RvY2tfc2VyaWVzICU+JSAKICBncm91cF9ieShzdG9ja19uYW1lX3Jvb3QpICU+JQogICAgICBzdW1tYXJpemUoCiAgICAgICAgbWluID0gbWluKGRhdGUsIG5hLnJtPVRSVUUpLAogICAgICAgIG1heCA9IG1heChkYXRlLCBuYS5ybT1UUlVFKSwKICAgICAgICByZWFsX2VzdGF0ZV9zdWJfc2VjdG9yID0gdW5pcXVlKHJlYWxfZXN0YXRlX3N1Yl9zZWN0b3IpLAogICAgICAgIG1hcmtldF9jYXBfX2NfX19fMzBfc2VwdGVtYmVyXzIwMjAgPSAKICAgICAgICAgIG1heChtYXJrZXRfY2FwX19jX19fXzMwX3NlcHRlbWJlcl8yMDIwKSwKICAgICAgICAuZ3JvdXBzID0gImtlZXAiCiAgICAgICkKc3RvY2tfc2VyaWVzX3N0YXRzX2FsbCRtYXJrZXRfY2FwX2ZyYWN0aW9uIDwtIAogIHN0b2NrX3Nlcmllc19zdGF0c19hbGwkbWFya2V0X2NhcF9fY19fX18zMF9zZXB0ZW1iZXJfMjAyMC9zdW0oc3RvY2tfc2VyaWVzX3N0YXRzX2FsbCRtYXJrZXRfY2FwX19jX19fXzMwX3NlcHRlbWJlcl8yMDIwKQpzdG9ja19zZXJpZXNfc3RhdHNfYWxsJHJlYWxfZXN0YXRlX3N1Yl9zZWN0b3IgPC0gTlVMTApzdG9ja19zZXJpZXNfc3RhdHNfYWxsCmBgYAoKCkZhaXJseSB3ZWxsIGRpc3RyaWJ1dGVkLgpgYGB7cn0KaGVhZChzdG9ja19zZXJpZXNfc3RhdHNfYWxsICU+JSBhcnJhbmdlKGFjcm9zcyhtYXJrZXRfY2FwX2ZyYWN0aW9uLCBkZXNjKSksIDEwKQpgYGAKCmBgYHtyLCBmaWcud2lkdGg9MjQsIGZpZy5oZWlnaHQ9MTJ9CnAgPC0gZ2dwbG90KGRhdGEgPSBzdG9ja19zZXJpZXMpICsgCiAgICAgICAgICAgICAgZ2VvbV9saW5lKGFlcyh4ID0gYXMuRGF0ZShkYXRlKSwgeSA9IHJldHVybnMsIGdyb3VwPXN0b2NrX25hbWVfcm9vdCwgYWxwaGE9MC4yKSkgKwogICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9ICJBbGwgdGlja2VycyIsCiAgICAgICAgICAgICAgICAgICB4ID0gInJlZmVyZW5jZSBtb250aCIsIHkgPSAiY2xvc2Ugc3RvY2sgdmFsdWUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwPSAiVGlja2VyIiwgY29sb3I9ICJUaWNrZXIiKQpnZ3Bsb3RseShwLCB3aWR0aD04ODAsIGhlaWdodD00NTApCmBgYAoKCgoKCgoK